function [target_image target_info source_values source_points] = warpImage(source_control_points, target_control_points, source_image, target_image, target_area, sample_ratios, interp_option)

% compute geometric points in the target_area
[XX YY] = meshgrid(1:sample_ratios(2):size(target_image, 2), 1:sample_ratios(1):size(target_image, 1));
sampled_mask = inpolygon(XX, YY, target_area(:, 1), target_area(:, 2));
masked_XX = XX(sampled_mask); 
masked_YY = YY(sampled_mask);

% find corresponding interpolated pixel values in the source image
target_points = [masked_XX(:) masked_YY(:)];
W = thinPlateSpline(target_control_points, source_control_points);
source_points = thinPlateWarp(target_points, target_control_points, W);
source_values = interp2(source_image, source_points(:, 1), source_points(:, 2), interp_option);

% fill in the region in the target_image
full_source_values = zeros(size(XX));
full_source_values(sampled_mask) = source_values;
target_mask = roipoly(target_image, target_area(:, 1), target_area(:, 2));
[ys xs] = find(target_mask);
interp_target_values = interp2(XX, YY, full_source_values, xs(:), ys(:), interp_option);
target_image(target_mask) = interp_target_values;

target_info.XX = XX;
target_info.YY = YY;
target_info.sampled_mask = sampled_mask;
target_info.target_mask = target_mask;
target_info.target_points = target_points;
